home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Environments / PowerMacOberon feb96 / Source / Find.Mod (.txt) < prev    next >
Encoding:
Oberon Text  |  1995-12-08  |  17.1 KB  |  446 lines  |  [TEXT/.Ob4]

  1. Syntax10.Scn.Fnt
  2. FoldElems
  3. Syntax10.Scn.Fnt
  4. (*------------------------------------------------------------
  5. Compare files.
  6. Search for a literal string in a sequence of files.
  7. Search for clients and imports of a specific module.
  8. Search for attributes in info elements
  9. Find.Diff ^
  10.     Compares two texts starting from the two most recent
  11.     selections. Sets new selections at the first position where the two
  12.     texts differ.
  13. Find.Domain {filename} ~
  14.     Specify the files in which Find.All should search for a pattern.
  15. Find.All ^
  16.     Searches the selection in the files specified with Find.Domain.
  17.     Lists all lines containing the pattern.
  18. Find.AllInfo ^
  19.     The selection must be of the form
  20.         item = pattern
  21.     where item is one of the headings in an info element
  22.     (Title, Author, ...) and pattern is any character sequence
  23.     up to the end of the selection.
  24.     Lists all modules specified with Find.Domain containing 
  25.     the pattern in their info elements.
  26. Find.Clients (name | ^)
  27.     List all client modules which import module <name>.  
  28.     Clients are searched in the same way as they would be searched for loading/opening.
  29. Find.Imports (name | ^)
  30.     List all modules imported by module <name>. The modules are listed together with their keys.
  31. ------------------------------------------------------------*)
  32. Syntax10i.Scn.Fnt
  33. InfoElems
  34. Alloc
  35. Syntax10.Scn.Fnt
  36. StampElems
  37. Alloc
  38. 8 Dec 95
  39. "Title": Find
  40. "Author": HM (mainly), CS (added AllInfo)
  41. "Abstract": Provides you with the possibility to search strings in several
  42.     files, to see which files are imported by several files, to see by which
  43.     files several files are imported and to search several files after additional
  44.     information (title, author, version, keywords etc.).
  45. "Keywords": search, import, client, additional info
  46. "Version": 1.0
  47. "From":  28.10.94 16:40:44
  48. "Until": 
  49. "Changes":
  50. "Hints": This text can again contain arbitrary text elements!
  51. MarkElems
  52. Alloc
  53. Syntax10.Scn.Fnt
  54.     VAR a, b: CHAR;
  55. BEGIN
  56.     Files.Read(r, a); Files.Read(r, b);
  57.     n := SHORT(ASH(ORD(a), 8) + ORD(b))
  58. END ReadInt;
  59. Syntax10.Scn.Fnt
  60.     VAR a, b, c, d: CHAR;
  61. BEGIN
  62.     Files.Read(r, a); Files.Read(r, b); Files.Read(r, c); Files.Read(r, d);
  63.     n := ASH(ORD(a), 24) + ASH(ORD(b), 16) + ASH(ORD(c), 8) + ORD(d)
  64. END ReadLInt;
  65. Syntax10.Scn.Fnt
  66.     VAR t: Texts.Text; beg, end, time: LONGINT;
  67. BEGIN
  68.     Texts.OpenScanner(s, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(s);
  69.     IF (s.class = Texts.Char) & (s.c = "^") THEN
  70.         Oberon.GetSelection(t, beg, end, time);
  71.         IF time >= 0 THEN
  72.             Texts.OpenScanner(s, t, beg); Texts.Scan(s)
  73.         END
  74. END ScanPar;
  75. Syntax10.Scn.Fnt
  76.     VAR v: MenuViewers.Viewer; x, y: INTEGER; t1: Texts.Text; menu: TextFrames.Frame; buf: Texts.Buffer;
  77. BEGIN
  78.     IF Files.Old("Edit.Menu.Text") = NIL THEN menu := TextFrames.NewMenu(name, stdMenu)
  79.     ELSE menu := TextFrames.NewMenu(name, "");
  80.         NEW(t1); Texts.Open(t1, "Edit.Menu.Text");
  81.         NEW(buf); Texts.OpenBuf(buf); Texts.Save(t1, 0, t1.len, buf); Texts.Append(menu.text, buf)
  82.     END;
  83.     Oberon.AllocateUserViewer(0, x, y);
  84.     v := MenuViewers.New(menu, TextFrames.NewText(t, 0), TextFrames.menuH, x, y)
  85. END OpenViewer;
  86. Syntax10.Scn.Fnt
  87.     CONST
  88.         bufSize = 31744; (*2**15 - 1024*)
  89.         textTag = 496; oldTextTag = -4095;
  90.         f: Files.File; r: Files.Rider;
  91.         n, pos: LONGINT;
  92.         i, j, i0: INTEGER;
  93.         ch, patj: CHAR;
  94.         found: BOOLEAN;
  95.         tab: ARRAY 265 OF SHORTINT;
  96.         text: ARRAY bufSize OF CHAR;
  97. BEGIN
  98.     (*----- open file *)
  99.     f := Files.Old(fn);
  100.     IF f = NIL THEN RETURN END;
  101.     Files.Set(r, f, 0); Files.ReadInt(r, i);
  102.     IF (i = textTag) OR (i = oldTextTag) THEN
  103.         pos := 0; (*Files.ReadLInt(r, pos); -- modified to search also in collapsed Fold segments*)
  104.         (*----- initialize tab *)
  105.         Texts.WriteString(w, "--- "); Texts.WriteString(w, fn); Texts.WriteLn(w);
  106.         FOR i := 0 TO 255 DO tab[i] := SHORT(m) END;
  107.         FOR i := 0 TO m-2 DO tab[ORD(pat[i])] := SHORT(m - i - 1) END;
  108.         patj := pat[m-1]; found := FALSE;
  109.         LOOP
  110.             (*----- read text[0..n-1] *)
  111.             n := Files.Length(f) - pos;
  112.             IF n > bufSize THEN n := bufSize END;
  113.             IF n < m THEN EXIT END;
  114.             Files.Set(r, f, pos); Files.ReadBytes(r, text, n);
  115.             (*----- search pat in text[0..n-1] *)
  116.             i := m - 1; j := i;
  117.             WHILE i < n DO
  118.                 IF text[i] = patj THEN i0 := i;
  119.                     REPEAT DEC(i); DEC(j) UNTIL (j < 0) OR (text[i] # pat[j]);
  120.                     IF j < 0 THEN
  121.                         (*------ found: print result *)
  122.                         found := TRUE;
  123.                         WHILE (i >= 0) & (text[i] # CR) & (text[i] >= TAB) DO DEC(i) END;
  124.                         INC(i);
  125.                         Files.Set(r, f, pos + i);
  126.                         REPEAT Files.Read(r, ch); Texts.Write(w, ch); INC(i) UNTIL (ch = CR) OR (ch < TAB) OR (r.eof)
  127.                     ELSE i := i + tab[ORD(text[i])]
  128.                     END;
  129.                     IF i <= i0 THEN i := i0 + 1 END;
  130.                     j := m - 1
  131.                 ELSE i := i + tab[ORD(text[i])]
  132.                 END
  133.             END;
  134.             pos := pos + i - m + 1
  135.         END;
  136.         IF found THEN Texts.WriteLn(w); Texts.Append(out, w.buf) ELSE Texts.OpenWriter(w) END
  137.     ELSE
  138.         Texts.WriteString(w, fn); Texts.WriteString(w, " is no text file"); Texts.WriteLn(w);
  139.         Texts.Append(Oberon.Log, w.buf)
  140. END Search;
  141. Syntax10.Scn.Fnt
  142.     VAR f: Files.File; r: Files.Rider; ch: CHAR; s: ARRAY 32 OF CHAR; i, j, dummy, entries, cmds, ptrs, imps: INTEGER; key: LONGINT;
  143. BEGIN
  144.     IF ~isDir THEN
  145.         f := Files.Old(name);
  146.         IF f # NIL THEN
  147.             i := 0; WHILE name[i] # 0X DO INC(i) END;
  148.             IF (i >= 3) & (name[i-3] = "O") & (name[i-2] = "b") & (name[i-1] = "j") THEN
  149.                 name[i-3] := "M"; name[i-2] := "o"; name[i-1] := "d";
  150.                 Files.Set(r, f, 6);
  151.                 ReadInt(r, entries); ReadInt(r, cmds); ReadInt(r, ptrs); ReadInt(r, dummy); ReadInt(r, imps);
  152.                 Files.Set(r, f, 34); REPEAT Files.Read(r, ch) UNTIL ch = 0X; (*skip name*)
  153.                 Files.Set(r, f, Files.Pos(r) + 1 + 2*entries + 1); (*skip entries*)
  154.                 FOR i := 1 TO cmds DO  (*skip commands*)
  155.                     REPEAT Files.Read(r, ch) UNTIL ch = 0X;
  156.                     ReadInt(r, dummy)
  157.                 END;
  158.                 Files.Set(r, f, Files.Pos(r) + 1 + 4*ptrs + 1); (*skip pointer offsets*)
  159.                 FOR i := 1 TO imps DO
  160.                     ReadLInt(r, key);
  161.                     j := 0; REPEAT Files.Read(r, ch); s[j] := ch; INC(j) UNTIL ch = 0X;
  162.                     IF s = fileName THEN Out.String("   "); Out.String(name); Out.Ln END
  163.                 END
  164.             END
  165.         END
  166. END CheckObjFile;
  167. Syntax10b.Scn.Fnt
  168. Syntax10.Scn.Fnt
  169.     VAR s: Texts.Scanner; f, last: File;
  170. BEGIN file := NIL; last := NIL;
  171.     ScanPar(s);
  172.     WHILE (s.class = Texts.Name) OR (s.class = Texts.String) DO
  173.         NEW(f); f.next := NIL;
  174.         IF last = NIL THEN file := f ELSE last.next := f END;
  175.         last := f;
  176.         COPY(s.s, f.name);
  177.         Texts.Scan(s);
  178.         WHILE (s.class = Texts.Char) & (s.c = "/") DO Texts.Scan(s); Texts.Scan(s) END
  179. END Domain;
  180. Syntax10.Scn.Fnt
  181. FoldElems
  182. Syntax10.Scn.Fnt
  183.         VAR t: Texts.Text; r: Texts.Reader; beg, end, time: LONGINT; ch: CHAR;
  184.     BEGIN
  185.         Oberon.GetSelection(t, beg, end, time);
  186.         IF time > 0 THEN
  187.             Texts.OpenReader(r, t, beg); m := 0;
  188.             WHILE beg < end DO Texts.Read(r, ch);
  189.                 IF m < 127 THEN pat[m] := ch END;
  190.                 INC(m); INC(beg)
  191.             END;
  192.             pat[m] := 0X
  193.         END;
  194.     END ReadPattern;
  195.     VAR pat: ARRAY 128 OF CHAR; m: INTEGER; f: File;
  196.     PROCEDURE ReadPattern (VAR pat: ARRAY OF CHAR; VAR m: INTEGER);    
  197. BEGIN
  198.     ReadPattern(pat, m);
  199.     out := TextFrames.Text("");
  200.     OpenViewer(pat, out); f := file;
  201.     WHILE f # NIL DO
  202.         Search(f.name, pat, m);
  203.         f := f.next
  204. END All;
  205. Syntax10.Scn.Fnt
  206. FoldElems
  207. Syntax10.Scn.Fnt
  208.         VAR time: LONGINT; v: Viewers.Viewer; x: INTEGER; f: Display.Frame;
  209.     BEGIN
  210.         time := -1; x := 0; F := NIL;
  211.         WHILE x < Display.Width DO
  212.             v := Viewers.This(x, 0);
  213.             WHILE v.state > 1 DO
  214.                 f := v.dsc.next;
  215.                 WITH f: TextFrames.Frame DO
  216.                     IF f.hasSel & (f.time > time) THEN F := f; pos := f.selbeg.pos; time := f.time END
  217.                 ELSE
  218.                 END;
  219.                 v := Viewers.Next(v)
  220.             END;
  221.             x := x + v.W
  222.         END;
  223.         IF F # NIL THEN TextFrames.RemoveSelection(F); TextFrames.RemoveCaret(F) END
  224.     END GetSelection;
  225. Syntax10.Scn.Fnt
  226.         VAR x: LONGINT;
  227.     BEGIN
  228.         IF pos > TextFrames.Pos(f, f.X + f.W - 1, f.Y) THEN 
  229.             x := pos - 150; IF x < 0 THEN x := 0 END;
  230.             TextFrames.Show(f, x)
  231.         END;
  232.         TextFrames.SetSelection(f, pos, pos+1)
  233.     END ShowSelection;
  234.     VAR f1, f2: TextFrames.Frame; p1, p2: LONGINT; r1, r2: Texts.Reader; ch1, ch2: CHAR;
  235.     PROCEDURE GetSelection(VAR F: TextFrames.Frame; VAR pos: LONGINT);    
  236.     PROCEDURE ShowSelection(f: TextFrames.Frame; pos: LONGINT);    
  237. BEGIN
  238.     GetSelection(f1, p1); GetSelection(f2, p2);
  239.     IF (f1 # NIL) & (f2 # NIL) THEN
  240.         Texts.OpenReader(r1, f1.text, p1); 
  241.         Texts.OpenReader(r2, f2.text, p2); 
  242.         REPEAT
  243.             Texts.Read(r1, ch1); INC(p1); Texts.Read(r2, ch2); INC(p2);
  244.         UNTIL (ch1 # ch2) OR (ch1 = 0X);
  245.         IF (ch1 = 0X) OR (ch2 = 0X) THEN DEC(p1); DEC(p2) END;
  246.         ShowSelection(f1, p1-1); ShowSelection(f2, p2-1)
  247. END Diff;
  248. Syntax10.Scn.Fnt
  249. Syntax10i.Scn.Fnt
  250. FoldElems
  251. Syntax10.Scn.Fnt
  252.         VAR t: Texts.Text; r: Texts.Reader; s: Texts.Scanner; beg, end, time: LONGINT; ch: CHAR;
  253.     BEGIN
  254.         Oberon.GetSelection(t, beg, end, time);
  255.         IF time > 0 THEN
  256.             Texts.OpenScanner(s, t, beg); Texts.Scan(s);
  257.             IF s.class IN {Texts.Name, Texts.String} THEN
  258.                 COPY(s.s, item);
  259.                 Texts.Scan(s);
  260.                 IF (s.class = Texts.Char) & (s.c = "=") THEN
  261.                     Texts.Scan(s);
  262.                     Texts.OpenReader(r, t, Texts.Pos(s) - 2); m := 0; beg := Texts.Pos(s) - 2;
  263.                     WHILE beg < end DO 
  264.                         Texts.Read(r, ch);
  265.                         IF m < (LEN(pat) - 1) THEN pat[m] := ch END;
  266.                         INC(m); INC(beg)
  267.                     END;
  268.                     pat[m] := 0X
  269.                 END;
  270.             END;
  271.         END;
  272.     END ReadPattern;
  273.     VAR pat: ARRAY 128 OF CHAR; item: ARRAY 16 OF CHAR; m: INTEGER; f: File;
  274.     PROCEDURE ReadPattern;    
  275. BEGIN
  276.     ReadPattern;
  277.     out := TextFrames.Text("");
  278.     OpenViewer(pat, out); f := file;
  279.     WHILE f # NIL DO
  280.         InfoSearch(f.name, pat, item);
  281.         f := f.next
  282. END AllInfo;
  283. Syntax10.Scn.Fnt
  284.     VAR d, cur, startup: Directories.Directory;
  285. BEGIN
  286.     d := Directories.This(path); cur := Directories.Current(); startup := Directories.Startup();
  287.     IF (d # NIL) & (d.path # cur.path) THEN
  288.         Directories.Enumerate(d, CheckObjFile);
  289.         IF d.path = startup.path THEN startupDone := TRUE END
  290. END CheckObjFileCB;
  291. Syntax10.Scn.Fnt
  292.     VAR i: INTEGER; d, cur, startup: Directories.Directory;
  293. BEGIN
  294.     In.Open; In.Name(fileName);
  295.     IF In.Done THEN
  296.         i := 0; WHILE fileName[i] # 0X DO INC(i) END;
  297.         IF (i >= 4) & (fileName[i-4] = ".") THEN fileName[i-4] := 0X END;
  298.         Out.String("modules importing "); Out.String(fileName); Out.Char(":"); Out.Ln;
  299.         cur := Directories.Current(); startup := Directories.Startup();
  300.         Directories.Enumerate(cur, CheckObjFile);
  301.         startupDone := cur.path = startup.path;
  302.         Directories.EnumeratePaths(CheckObjFileCB);
  303.         IF ~startupDone THEN Directories.Enumerate(startup, CheckObjFile) END
  304.     END;
  305. END Clients;
  306. Syntax10.Scn.Fnt
  307.     CONST TAB = 9X;
  308.     VAR f: Files.File; r: Files.Rider; ch: CHAR; a: ARRAY 256 OF CHAR; i, j, dummy, entries, cmds, ptrs, imps: INTEGER; key: LONGINT;
  309. BEGIN
  310.     In.Open; In.Name(a);
  311.     IF In.Done THEN
  312.         i := 0; WHILE a[i] # 0X DO INC(i) END;
  313.         IF (i >= 4) & (a[i-4] = ".") THEN i := i - 4 ELSE a[i] := "." END;
  314.         a[i+1] := "O"; a[i+2] := "b"; a[i+3] := "j"; a[i+4] := 0X;
  315.         f := Files.Old(a);
  316.         IF f # NIL THEN
  317.             Files.Set(r, f, 6);
  318.             ReadInt(r, entries); ReadInt(r, cmds); ReadInt(r, ptrs); ReadInt(r, dummy); ReadInt(r, imps);
  319.             Files.Set(r, f, 34); REPEAT Files.Read(r, ch) UNTIL ch = 0X; (*skip name*)
  320.             Files.Set(r, f, Files.Pos(r) + 1 + 2*entries + 1); (*skip entries*)
  321.             FOR i := 1 TO cmds DO  (*skip commands*)
  322.                 REPEAT Files.Read(r, ch) UNTIL ch = 0X;
  323.                 ReadInt(r, dummy)
  324.             END;
  325.             Files.Set(r, f, Files.Pos(r) + 1 + 4*ptrs + 1); (*skip pointer offsets*)
  326.             Out.String(a); Out.Char(TAB); Out.Char("["); Out.Int(key, 0); Out.String("] imports:"); Out.Ln;
  327.             FOR i := 1 TO imps DO
  328.                 ReadLInt(r, key);
  329.                 j := 0; REPEAT Files.Read(r, ch); a[j] := ch; INC(j) UNTIL ch = 0X;
  330.                 Out.Char(TAB); Out.String(a); Out.Char(TAB); Out.Char("["); Out.Int(key, 0); Out.Char("]"); Out.Ln
  331.             END
  332.         END
  333. END Imports;
  334. Documentation
  335. MODULE Find;    
  336. IMPORT Display, Files, Directories, Oberon, Viewers, MenuViewers, TextFrames, Texts, In, Out, InfoElems, Strings;
  337. CONST
  338.     stdMenu = "System.Close  System.Copy  System.Grow  Edit.Search  Edit.Store ";
  339.     CR = 0DX; TAB = 09X;
  340.     File = POINTER TO FileDesc;
  341.     FileDesc = RECORD
  342.         name: ARRAY 256 OF CHAR;
  343.         next: File
  344.     END;
  345.     file: File;
  346.     fileName: ARRAY 256 OF CHAR;
  347.     w: Texts.Writer;
  348.     out: Texts.Text;
  349.     startupDone: BOOLEAN;    (* state for CheckObjFileCB *)
  350. PROCEDURE 
  351. ReadInt (VAR r: Files.Rider; VAR n: INTEGER);    
  352. PROCEDURE 
  353. ReadLInt (VAR r: Files.Rider; VAR n: LONGINT);    
  354. PROCEDURE 
  355. ScanPar (VAR s: Texts.Scanner);    
  356. PROCEDURE 
  357. OpenViewer(name: ARRAY OF CHAR; t: Texts.Text);    
  358. PROCEDURE 
  359. Search (fn: ARRAY OF CHAR; pat: ARRAY OF CHAR; m: INTEGER);    
  360. PROCEDURE 
  361. CheckObjFile (d: Directories.Directory; name: ARRAY OF CHAR; isDir: BOOLEAN; VAR continue: BOOLEAN);    
  362. (* -- commands -- *)
  363. PROCEDURE 
  364. Domain*;    (* {filename} ~ *)    
  365. PROCEDURE 
  366. All*;    (* ^ *)    
  367. PROCEDURE 
  368. Diff*;    (* compares two texts from the last two selections; sets selection to first difference *)    
  369. (* -- PowerMac-specific commands -- *)
  370. PROCEDURE 
  371. InfoSearch (fn: ARRAY OF CHAR; pat: ARRAY OF CHAR; item: ARRAY OF CHAR);
  372.         t, infoT: Texts.Text; r, infoR: Texts.Reader;
  373.         ch, commentCh: CHAR; menuItem: ARRAY 16 OF CHAR;
  374.         text: ARRAY 10000 OF CHAR;
  375.         i: LONGINT; found: BOOLEAN;
  376. BEGIN
  377.     Texts.WriteString(w, "--- "); Texts.WriteString(w, fn); Texts.WriteString(w, ", matches for "); Texts.WriteString(w, item);
  378.     Texts.WriteString(w, " = "); Texts.WriteString(w, pat); Texts.WriteLn(w);
  379.     found := FALSE;
  380.     NEW(t); Texts.Open(t, fn);
  381.     Texts.OpenReader(r, t, 0); Texts.ReadElem(r);
  382.     WHILE ~r.eot DO
  383.         IF r.elem IS InfoElems.Elem THEN    (* InfoElem found *)
  384.             infoT := r.elem(InfoElems.Elem).menu;    (* get text of InfoElem *)
  385.             Texts.OpenReader(infoR, infoT, 0); Texts.Read(infoR, ch);
  386.             WHILE ~infoR.eot DO
  387.                 WHILE (~infoR.eot) & (ch # '"') & (ch # "'") DO Texts.Read(infoR, ch) END;
  388.                 IF ~infoR.eot THEN commentCh := ch END; 
  389.                 Texts.Read(infoR, ch); i := 0;
  390.                 WHILE (~infoR.eot) & (ch # commentCh) DO 
  391.                     menuItem[i] := ch;
  392.                     Texts.Read(infoR, ch); INC(i)
  393.                 END;
  394.                 menuItem[i] := 0X;
  395.                 WHILE (~infoR.eot) & ((ch = "'") OR (ch = '"') OR (ch = " ") OR (ch = TAB) OR (ch = ":")) DO
  396.                     Texts.Read(infoR, ch)
  397.                 END;
  398.                 i := 0;
  399.                 WHILE (~infoR.eot) & (ch # '"') & (ch # "'") & (i < LEN(text) - 1) DO
  400.                     IF (ch # TAB) & (ch # CR) THEN text[i] := ch; INC(i) END;
  401.                     Texts.Read(infoR, ch)
  402.                 END;
  403.                 text[i] := 0X;
  404.                 IF menuItem = item THEN
  405.                     IF Strings.Match(text, pat) THEN i := 0; found := TRUE;
  406.                         WHILE text[i] # 0X DO Texts.Write(w, text[i]); INC(i) END
  407.                     END
  408.                 END
  409.             END
  410.         END;
  411.         Texts.ReadElem(r)
  412.     END;
  413.     IF found THEN Texts.WriteLn(w); Texts.Append(out, w.buf) ELSE Texts.OpenWriter(w) END
  414.             Texts.OpenScanner(menuS, menuT, 0); Texts.Scan(menuS);
  415.             WHILE ~menuS.eot DO
  416.                 IF (menuS.class = Texts.String) & (menuS.s = item) THEN (* if it is the right item *)
  417.                     Texts.OpenReader(copyR, t, Texts.Pos(menuS) - 2); Texts.Read(copyR, copyCh); i := 0; r2 := r;
  418.                     WHILE (~copyR.eot) & (copyCh # '"') DO INC(i); Texts.Read(copyR, copyCh) END;
  419.                     NEW(text, i + 1); r := r2; i := 0;
  420.                     WHILE (~copyR.eot) & (copyCh # '"') DO
  421.                         INC(i); text[i] := copyCh; Out.Char(copyCh);
  422.                         Texts.Read(copyR, copyCh)
  423.                     END;
  424.                     text[i] := 0X;
  425.                     IF Match(text^, pat, i - 1, m - 1) THEN FOR i := 0 TO i DO Texts.Write(w, ch) END END;
  426.                     Texts.OpenScanner(menuS, t, Texts.Pos(copyR) - 1); 
  427.                 END;
  428.                 Texts.Scan(menuS);
  429.             END
  430.         END; (* character was no InfoElem *)
  431.         Texts.Read(r, ch)
  432.     END;
  433. END InfoSearch;
  434. PROCEDURE 
  435. AllInfo*; (** ^         format: item = searchPattern where item IN {"Title", "Author", "Abstract", 
  436.                                                 "Keywords", "Version", "From", "Until", "Hints", "Changes"}, searchPattern 
  437.                                                 must match exactly or contain asterisks *)    
  438. PROCEDURE CheckObjFileCB (path: ARRAY OF CHAR; VAR continue: BOOLEAN);
  439. PROCEDURE 
  440. Clients*;    
  441. PROCEDURE 
  442. Imports*;    
  443. BEGIN
  444.     file := NIL; Texts.OpenWriter(w)
  445. END Find.
  446.